package internal

import (
	"encoding/gob"
	"io"
	"log"
	"os"
	"sync"
)

type urlStore struct {
	urls map[string]string
	mu   sync.RWMutex
	file *os.File
}

type record struct {
	Key, URL string
}

func NewURLStore(fileName string) *urlStore {
	s := &urlStore{urls: make(map[string]string)}
	file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatalln("Error opening URLStore:", err)
	}
	s.file = file
	if err := s.load(); err != nil {
		log.Println("Error loading URLStore:", err)
	}
	return s
}

// Get 获取key对应的url
func (u *urlStore) Get(key string) string {
	u.mu.RLock()
	defer u.mu.RUnlock()
	return u.urls[key]
}

//Set 设置key -> url 标签对
func (u *urlStore) Set(key, url string) bool {
	u.mu.Lock()
	defer u.mu.Unlock()
	if _, present := u.urls[key]; present {
		return false
	}
	u.urls[key] = url
	return true
}

//Count 计算存储量
func (u *urlStore) Count() int {
	u.mu.RLock()
	defer u.mu.RUnlock()
	return len(u.urls)
}

func (u *urlStore) Put(url string) string {
	key, err := genKey(4)
	if err == nil {
		if ok := u.Set(key, url); ok {
			if err := u.save(key, url); err != nil {
				log.Println("Error saving to URLStore:", err)
			}

			return key
		}
	}
	return ""
}

//load 从文件中加载配置
func (u *urlStore) load() error {
	if _, err := u.file.Seek(0, 0); err != nil {
		return err
	}
	d := gob.NewDecoder(u.file)
	var err error
	for err == nil {
		var r record
		if err = d.Decode(&r); err == nil {
			u.Set(r.Key, r.URL)
		}
	}
	if err == io.EOF {
		return nil
	}
	return err
}

//save 保存到文本
func (u *urlStore) save(key, url string) error {
	encode := gob.NewEncoder(u.file)
	return encode.Encode(record{key, url})
}
